package com.app.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.app.exception.BaseException;
import com.app.mapper.MessageBoxMapper;
import com.app.mapper.PrizeActivityMapper;
import com.app.mapper.VoucherRecordMapper;
import com.app.model.*;
import com.app.service.*;
import com.app.utils.CommonHelp;
import com.app.vo.PrizeActivityVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 转盘活动 服务实现类
 * </p>
 *
 * @author yoominic
 * @since 2023-12-16
 */
@Service
@Slf4j
public class PrizeActivityServiceImpl extends ServiceImpl<PrizeActivityMapper, PrizeActivity> implements IPrizeActivityService {
    @Autowired
    private UserServiceImpl userService;
    @Autowired
    private IPrizeService iPrizeService;
    @Autowired
    private IntegralRecordService integralRecordService;
    @Autowired
    private ILotteryRecordService iLotteryRecordService;
    @Autowired
    private VoucherRecordMapper voucherRecordMapper;
    @Autowired
    private MessageBoxMapper messageBoxMapper;
    @Autowired
    private BusinessService businessService;

    @Override
    public PrizeActivityVo activityList(Integer page, Integer limit, String activityName) {
        QueryWrapper<PrizeActivity> activityQueryWrapper = new QueryWrapper<>();
        if (!StrUtil.hasBlank(activityName)) {
            activityQueryWrapper.like("Activity_name", activityName);
        }
        activityQueryWrapper.orderByDesc("id");
        Page<PrizeActivity> activityPage = new Page<>(page, limit);
        Page<PrizeActivity> selectPage = super.baseMapper.selectPage(activityPage, activityQueryWrapper);
        List<PrizeActivity> activityList = selectPage.getRecords();
        for (PrizeActivity activity : activityList) {
            QueryWrapper<Prize> prizeQueryWrapper = new QueryWrapper<>();
            prizeQueryWrapper.eq("game_id", activity.getId());
            Prize prize = iPrizeService.getOne(prizeQueryWrapper);
            if (prize != null && prize.getPrize() != null) {
                activity.setPrizeId(prize.getId());
                List<Prize> prizeList = JSON.parseObject(prize.getPrize(), new TypeReference<List<Prize>>() {
                });
                for (Prize prize1 : prizeList) {
                    if (prize1.getPrizeType() == 1) {
                        prize1.setPrizeTypeText("实物");
                    }
                    if (prize1.getPrizeType() == 2) {
                        prize1.setPrizeTypeText("积分");
                    }
                    if (prize1.getPrizeType() == 3) {
                        prize1.setPrizeTypeText("益联券");
                    }
                    if (prize1.getPrizeType() == 4) {
                        prize1.setPrizeTypeText("谢谢参与");
                    }
                }
                activity.setPrizeList(prizeList);
            }
        }
        PrizeActivityVo vo = new PrizeActivityVo();
        vo.setList(activityList);
        vo.setCount((int) selectPage.getTotal());
        return vo;
    }

    @Override
    public Object getActivityList(Integer userId, String activityName) throws ParseException {
        QueryWrapper<PrizeActivity> activityQueryWrapper = new QueryWrapper<>();
        activityQueryWrapper.eq("status", 1);
        if (StrUtil.isNotBlank(activityName)) {
            activityQueryWrapper.like("name", activityName);
        }
        activityQueryWrapper.orderByDesc("end_time");
        List<PrizeActivity> activities = super.baseMapper.selectList(activityQueryWrapper);
        if (activities.isEmpty()) {
            return "暂无活动";
        }
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        for (PrizeActivity activity : activities) {
            Prize prize = getPrizeList(activity.getId());
            if (prize==null) {
                return "暂无活动";
            }
            List<Prize> list = JSON.parseObject(prize.getPrize(), new TypeReference<List<Prize>>() {
            });
            activity.setPrizeList(list);
            String now = DateUtil.now();
            Date endTime = dateFormat.parse(activity.getEndTime());
            Date startTime = dateFormat.parse(activity.getStartTime());
            Date nowTime = dateFormat.parse(now);
            if (endTime.getTime() < nowTime.getTime()) {
                activity.setStatus(2);
                super.baseMapper.updateById(activity);
                return "活动已结束";
            }
            if (startTime.getTime() > nowTime.getTime()) {
                activity.setStatus(2);
                super.baseMapper.updateById(activity);
                return "活动未开始";
            }
        }
        Integer userTodayCount = iLotteryRecordService.getUserTodayCount(userId, activities.get(0).getId());
        activities.get(0).setUserTodayCount(userTodayCount);
        List<LotteryRecord> newRecords = iLotteryRecordService.getNewRecords(activities.get(0).getId());
        activities.get(0).setLotteryRecords(newRecords);
        return activities.get(0);
    }

    @Override
    public Object raffle(UserModel userModel, Integer activityId) {
        //获取抽奖活动信息
        QueryWrapper<PrizeActivity> activityQueryWrapper = new QueryWrapper<>();
        activityQueryWrapper.eq("status", 1);
        activityQueryWrapper.eq("id", activityId);
        List<PrizeActivity> activities = super.baseMapper.selectList(activityQueryWrapper);
        //获取奖品列表
        Prize prizeInfo = getPrizeList(activityId);
        List<Prize> list = JSON.parseObject(prizeInfo.getPrize(), new TypeReference<List<Prize>>() {
        });
        Optional<Prize> optional = list.stream().filter(prize -> prize.getPrizeType() == 4).findFirst();
        boolean present = optional.isPresent();
        for (Prize prize : list) {
            prize.setGameId(activityId);
            if (prize.getPrizeValue() > 0 && prize.getCurrentNum() != null && prize.getCurrentNum().equals(prize.getPrizeValue())) {
                if (present) {
                    Prize prize1 = optional.get();
                    prize1.setWeight(prize1.getWeight() + prize.getWeight());
                }
                prize.setWeight(0);
            }
        }
        //有次数限制的抽奖
        Integer userTodayCount = iLotteryRecordService.getUserTodayCount(userModel.getId(), activityId);
        if (activities.get(0).getDayLimit() > userTodayCount) {
            if (activities.get(0).getFreeFrequency() <= userTodayCount) {
                //获取付费情况
                //券
                Integer consumptionVoucher = activities.get(0).getConsumptionVoucher();
                //积分
                Integer consumptionPoints = activities.get(0).getConsumptionPoints();
                //扣减
                if (userModel.getVoucher()< consumptionVoucher) {
                    return "益联券不足";

                }
                if (userModel.getIntegral()< consumptionPoints) {
                    return "积分不足";

                }
                userModel.setVoucher(userModel.getVoucher() - consumptionVoucher);
                userModel.setIntegral(userModel.getIntegral() - consumptionPoints);
                userService.updateById(userModel);
                //若券或者积分不为0，则新增券记录、积分记录
                if (consumptionPoints > 0) {
                    //插入积分记录
                    IntegralRecordModel integralRecordModel = new IntegralRecordModel();
                    integralRecordModel.setName("使用益积分抽奖");
                    integralRecordModel.setTypeName("抽奖");
                    String amountIntegral = "-" + consumptionPoints + "分";
                    integralRecordModel.setIntegral(amountIntegral);
                    integralRecordModel.setUserId(userModel.getId());
                    integralRecordModel.setCreateTime(CommonHelp.getNowTimestamp());
                    integralRecordModel.setVoucherType(0);
                    integralRecordModel.setVoucherAmount(-Double.valueOf(consumptionPoints));
                    integralRecordService.save(integralRecordModel);
                }
                if (consumptionVoucher > 0) {
                    //插入益联券记录
                    VoucherRecordModel voucherRecordModel = new VoucherRecordModel();
                    voucherRecordModel.setName("使用益联券抽奖");
                    voucherRecordModel.setTypeName("抽奖");
                    String amountVoucher = "-" + consumptionVoucher + "券";
                    voucherRecordModel.setVoucher(amountVoucher);
                    voucherRecordModel.setUserId(userModel.getId());
                    voucherRecordModel.setCreateTime(CommonHelp.getNowTimestamp());
                    voucherRecordModel.setVoucherType(0);
                    voucherRecordModel.setVoucherAmount(-Double.valueOf(consumptionVoucher));
                    voucherRecordMapper.insert(voucherRecordModel);
                }
            }
            Prize prize = lottery(list);

            //抽奖逻辑命中规则
            prize=checkWhetherCurrentHitPrizeIsInKind(userModel.getId(),prize);

            //更新当前命中次数
            updateCurrentNum(prizeInfo, list, prize);
            //增加抽奖记录
            addRaffleRecord(userModel.getId(), prize);
            //发放奖励
            distributeRewards(userModel.getId(), prize);

            return prize;
        } else {
            return "今日次数不足";
        }
    }

    /**
     * 检查当前命中奖品是否是实物
     *
     * @param userId 用户id
     * @param prize  奖品
     * @return {@link Prize}
     */
    public Prize checkWhetherCurrentHitPrizeIsInKind(Integer userId,Prize prize)
    {
        //如果存在之前抽到的奖品还没领取
        if(checkWhetherCurrentUserHasNotReceivedRealPrize(userId))
        {
            //获取整个json对象
            QueryWrapper<Prize> prizeQueryWrapper=new QueryWrapper<>();
            prizeQueryWrapper.eq("game_id",prize.getGameId());
            Prize prizeJson=this.iPrizeService.getOne(prizeQueryWrapper);
            if(prizeJson!=null)
            {
                // 解析 JSON 数组
                List<Prize> prizes = JSONUtil.toList(prizeJson.getPrize(),Prize.class);
                // 过滤出 prizeType 为 4 的奖品
                List<Prize> unWinPrizes = prizes.stream()
                        .filter(p -> p.getPrizeType() == 4)
                        .collect(Collectors.toList());
                Prize unWinPrize=unWinPrizes.get(0);
                //如果为实物，直接命中为谢谢参与
                if(prize.getPrizeType()==1)
                {
                    Console.log("----------修改命中逻辑");
                    prize=unWinPrize;
                }
            }
        }
        return prize;
    }

    /**
     *
     * 检查当前用户是否领取到实物奖品
     *
     * @param userId 用户id
     */
    public  Boolean checkWhetherCurrentUserHasNotReceivedRealPrize(Integer userId)
    {
        QueryWrapper<LotteryRecord> lotteryRecordQueryWrapper=new QueryWrapper<>();
        lotteryRecordQueryWrapper.eq("user_id",userId);
        lotteryRecordQueryWrapper.eq("is_hit",1);
        lotteryRecordQueryWrapper.eq("type",1);
        lotteryRecordQueryWrapper.eq("is_send",1);
        Integer count=this.iLotteryRecordService.count(lotteryRecordQueryWrapper);
        if(count>0)
        {
            return true;
        }
        return false;
    }


    /**
     * 更新当前num
     *
     * @param list      列表
     * @param prize     奖品
     * @param prizeInfo 奖品信息
     */
    private void updateCurrentNum(Prize prizeInfo, List<Prize> list, Prize prize) {
           for (Prize value : list) {
               if (value.getPid().equals(prize.getPid())) {
                   value.setCurrentNum(value.getCurrentNum() + 1);
               }
           }
            prizeInfo.setPrize(JSON.toJSONString(list));
           iPrizeService.updateById(prizeInfo);
    }

    /**
     * 获取奖品列表
     *
     * @param activityId 活动id
     * @return {@link List}<{@link Prize}>
     */
    private Prize getPrizeList(Integer activityId) {
        QueryWrapper<Prize> prizeQueryWrapper = new QueryWrapper<>();
        prizeQueryWrapper.eq("game_id", activityId);
        prizeQueryWrapper.last("limit 1");
        Prize prize=iPrizeService.getOne(prizeQueryWrapper);
        return prize;
    }

    /**
     * 分发奖励
     *
     * @param prize 奖品
     */
    private void distributeRewards(Integer userId, Prize prize) {
        int type = prize.getPrizeType();
        UserModel userModel = userService.getById(userId);
        try {
            switch (type) {
                // 实物
                case 1:
                    break;
                // 发放积分
                case 2:
                    if(prize.getValue()>0)
                    {
                        //插入积分记录
                        IntegralRecordModel integralRecordModel = new IntegralRecordModel();
                        integralRecordModel.setName("幸运大转盘抽奖");
                        integralRecordModel.setTypeName("抽奖");
                        String amountIntegral = "+" + prize.getValue() + "分";
                        integralRecordModel.setIntegral(amountIntegral);
                        integralRecordModel.setUserId(userId);
                        integralRecordModel.setCreateTime(CommonHelp.getNowTimestamp());
                        integralRecordModel.setVoucherType(1);
                        integralRecordModel.setVoucherAmount(Double.valueOf(prize.getValue()));
                        integralRecordService.save(integralRecordModel);
                        //更新用户积分
                        Double integral = userModel.getIntegral();
                        integral = integral + prize.getValue();
                        userModel.setIntegral(integral);
                        userService.updateById(userModel);
                    }
                    break;
                //发放益联券
                case 3:
                    //插入益联券记录
                    if(prize.getValue()>0)
                    {
                        VoucherRecordModel voucherRecordModel = new VoucherRecordModel();
                        voucherRecordModel.setName("幸运大转盘抽奖");
                        voucherRecordModel.setTypeName("抽奖");
                        String amountVoucher = "+" + prize.getValue() + "券";
                        voucherRecordModel.setVoucher(amountVoucher);
                        voucherRecordModel.setUserId(userId);
                        voucherRecordModel.setCreateTime(CommonHelp.getNowTimestamp());
                        voucherRecordModel.setVoucherType(1);
                        voucherRecordModel.setVoucherAmount(Double.valueOf(prize.getValue()));
                        voucherRecordMapper.insert(voucherRecordModel);
                        //消息盒子
                        MessageBoxModel messageBoxModel = new MessageBoxModel();
                        messageBoxModel.setUserId(userId);
                        messageBoxModel.setQuiltUserId(userId);
                        messageBoxModel.setTypeName("抽奖");
                        messageBoxModel.setVoucher(Double.valueOf(prize.getValue()));
                        messageBoxModel.setNotes("抽奖奖励发放");
                        messageBoxModel.setCreateTime(CommonHelp.getNowTimestamp());
                        messageBoxModel.setOrderSn("无");
                        messageBoxMapper.insert(messageBoxModel);
                        //更新用户益联券
                        Double voucher = userModel.getVoucher();
                        voucher = voucher + prize.getValue();
                        userModel.setVoucher(voucher);
                        userService.updateById(userModel);
                    }
                    break;
                // 谢谢参与
                case 4:
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加积分记录
     *
     * @param activities 活动
     */
//    private void addIntegralRecord(List<PrizeActivity> activities) {
//        IntegralRecord integralRecord = new IntegralRecord();
//        integralRecord.setUserId(StpUtil.getLoginIdAsLong());
//        integralRecord.setIntegral(activities.get(0).getIntegral());
//        integralRecord.setLastUpdateTime(LocalDateTime.now());
//        integralRecord.setSourceType(2);
//        integralRecord.setType(3);
//        integralRecord.setStatus(1);
//        integralRecord.setCreateTime(LocalDateTime.now());
//        iIntegralRecordService.save(integralRecord);
//    }

    /**
     * 添加抽奖记录
     *
     * @param prize 奖品
     */
    private void addRaffleRecord(Integer userId, Prize prize) {
        log.info(prize.toString());
        LotteryRecord lotteryRecord = new LotteryRecord();
        lotteryRecord.setUserId(userId);
        lotteryRecord.setDrawTime(LocalDateTime.now());
        lotteryRecord.setGameId(prize.getGameId());
        if (prize.getPrizeType() == 4) {
            lotteryRecord.setIsHit(0);
        } else {
            lotteryRecord.setIsHit(1);
        }
        if (prize.getPrizeType() == 2 || prize.getPrizeType() == 3) {
            lotteryRecord.setIsSend(2);
        } else {
            lotteryRecord.setIsSend(1);
        }
        lotteryRecord.setOrderSn(IdUtil.fastSimpleUUID());
        lotteryRecord.setType(prize.getPrizeType());
        lotteryRecord.setHitPrize(prize.getPrizeName());
        if(prize.getPrizeType()==1)
        {
            //默认彩票过期天数为7天
            Integer defaultExpiredLotteryDays=7;
            //抽奖配置如果不为null
            if(prize.getEffectiveDuration()!=null)
            {
                //默认过期时间为抽奖配置
                defaultExpiredLotteryDays=prize.getEffectiveDuration();
                //设置抽奖记录的领取时间为当前时间+抽奖配置
                Date claimDeadline=DateUtil.offsetDay(new Date(),defaultExpiredLotteryDays);
                //实体有效领取截止时间设置
                lotteryRecord.setEffectiveTime(claimDeadline);
            }
            if(prize.getBussesType()==0)
            {
                lotteryRecord.setAddress(prize.getAddress());
                lotteryRecord.setBussesType(prize.getBussesType());
            }else if(prize.getBussesType()==1){
                lotteryRecord.setBussesType(prize.getBussesType());
                lotteryRecord.setBussinessId(prize.getBusinessId());
                if(prize.getBusinessId()!=null)
                {
                    BusinessModel bussiness = businessService.getById(prize.getBusinessId());
                    if(bussiness!=null)
                    {
                        lotteryRecord.setAddress(bussiness.getAddress());
                    }
                }

            }
        }

        iLotteryRecordService.save(lotteryRecord);
    }

    /**
     * 判断是否中奖
     *
     * @param prizeList 奖品列表
     * @return {@link Prize}
     */
    public static Prize lottery(List<Prize> prizeList) {
        //按照权重从小到大排序奖品
        prizeList.sort(Comparator.comparingInt(Prize::getWeight));
        //计算节点 节点的数量比奖品的数量多一个，即0
        List<Integer> nodeList = new ArrayList<>();
        //第一个节点为0
        nodeList.add(0);
        for (Prize prize : prizeList) {
            //每一个节点等于前一个节点+当前奖品的权重
            nodeList.add(nodeList.get(nodeList.size() - 1) + prize.getWeight());
        }
        //生成 0-结束节点 的随机数
        int randomInt = RandomUtil.randomInt(0, nodeList.get(nodeList.size() - 1));
        //最终抽奖逻辑 此处需要从第二个节点开始遍历
        for (int i = 1; i < nodeList.size(); i++) {
            //本次节点
            Integer endNode = nodeList.get(i);
            //前一个节点
            Integer startNode = nodeList.get(i - 1);
            //若随机数大于等于前一个节点并且小于本节点，在prizeList中位于i-1位置的奖品为抽中奖品
            //Tip：比较大小时，左闭右开与左开右闭都可以，不影响整体概率
            if (randomInt >= startNode
                    && randomInt < endNode) {
                return prizeList.get(i - 1);
            }
        }
        throw new RuntimeException("程序异常 生成的随机数不在任何奖品区间内");
    }
}
